package com.lktx.sso.admin.service;

import cn.hserver.core.ioc.annotation.Autowired;
import cn.hserver.core.ioc.annotation.Bean;
import cn.hutool.core.util.StrUtil;
import com.lktx.sso.admin.entity.*;
import com.lktx.sso.admin.mapper.*;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;

import java.util.*;
import java.util.stream.Collectors;

/**
 * app应用访问控制 服务类
 */
@Slf4j
@Bean
public class SsoAppAccessPolicyService {

    @Autowired
    private SsoAppAccessPolicyMapper mapper;

    @Autowired
    private SsoUserMapper ssoUserMapper;

    @Autowired
    private SsoUserGroupMappingMapper ssoUserGroupMappingMapper;

    @Autowired
    private SsoUserGroupMapper ssoUserGroupMapper;

    @Autowired
    private SsoOrganizationMapper ssoOrganizationMapper;

    /**
     * 分页查询列表
     *
     * @param page   分页对象
     * @param entity 查询实体
     * @return 所有数据
     */
    public Page<SsoAppAccessPolicy> page(Page<SsoAppAccessPolicy> page, SsoAppAccessPolicy entity) {
        Page<SsoAppAccessPolicy> paginate = mapper.paginate(page, new QueryWrapper()
                        .eq(SsoAppAccessPolicy::getSsoAppId, entity.getSsoAppId(),entity.getSsoAppId()!=null)
                .like(SsoAppAccessPolicy::getSubjectType, entity.getSubjectType(), !Objects.isNull(entity.getSubjectType()))
                .orderBy(SsoAppAccessPolicy::getSsoAccessPolicyId, false)
        );

        List<SsoAppAccessPolicy> records = paginate.getRecords();
        Map<SsoAppAccessPolicy.SubjectType, List<Integer>> collect = records.stream()
                .collect(Collectors.groupingBy(
                        SsoAppAccessPolicy::getSubjectType,
                        Collectors.mapping(SsoAppAccessPolicy::getSubjectId, Collectors.toList())
                ));
        List<Integer> integers = collect.get(SsoAppAccessPolicy.SubjectType.USER);
        if (!Objects.isNull(integers)) {
            List<SsoUser> ssoUsers = ssoUserMapper.selectListByQuery(new QueryWrapper().in(SsoUser::getSsoUserId, integers));
            Map<Integer, SsoUser> ssoUserMap = ssoUsers.stream()
                    .collect(Collectors.toMap(SsoUser::getSsoUserId, user -> user));
            paginate.map(record -> {
                if (record.getSubjectType() == SsoAppAccessPolicy.SubjectType.USER) {
                    record.setSubObj(ssoUserMap.get(record.getSubjectId()));
                }
                return record;
            });
        }
        List<Integer> groupIntegers = collect.get(SsoAppAccessPolicy.SubjectType.USER_GROUP);
        if (!Objects.isNull(groupIntegers)) {
            List<SsoUserGroup> ssoUsers = ssoUserGroupMapper.selectListByQuery(new QueryWrapper().in(SsoUserGroup::getSsoUserGroupId, groupIntegers));
            Map<Integer, SsoUserGroup> ssoUserMap = ssoUsers.stream()
                    .collect(Collectors.toMap(SsoUserGroup::getSsoUserGroupId, user -> user));
            paginate.map(record -> {
                if (record.getSubjectType() == SsoAppAccessPolicy.SubjectType.USER_GROUP) {
                    record.setSubObj(ssoUserMap.get(record.getSubjectId()));
                }
                return record;
            });
        }

        List<Integer> orgIntegers = collect.get(SsoAppAccessPolicy.SubjectType.ORGANIZATION);
        if (!Objects.isNull(orgIntegers)) {
            List<SsoOrganization> ssoUsers = ssoOrganizationMapper.selectListByQuery(new QueryWrapper().in(SsoOrganization::getSsoOrganizationId, orgIntegers));
            Map<Integer, SsoOrganization> ssoUserMap = ssoUsers.stream()
                    .collect(Collectors.toMap(SsoOrganization::getSsoOrganizationId, user -> user));
            paginate.map(record -> {
                if (record.getSubjectType() == SsoAppAccessPolicy.SubjectType.ORGANIZATION) {
                    SsoOrganization ssoUser = ssoUserMap.get(record.getSubjectId());
                    record.setSubObj(ssoUser);
                }
                return record;
            });
        }

        return paginate;
    }

    /**
     * 不分页查询列表
     *
     * @param entity 实体对象
     * @return 查询结果
     */
    public List<SsoAppAccessPolicy> list(SsoAppAccessPolicy entity) {
        return mapper.selectListByQuery(new QueryWrapper()
                .like(SsoAppAccessPolicy::getSubjectType, entity.getSubjectType(), !Objects.isNull(entity.getSubjectType()))
                .orderBy(SsoAppAccessPolicy::getSsoAccessPolicyId, false)
        );
    }

    /**
     * 通过主键查询单条数据
     *
     * @param id 主键
     * @return 单条数据
     */
    public SsoAppAccessPolicy getById(Integer id) {
        return mapper.selectOneById(id);
    }

    public boolean checkByUserIdAccess(Integer ssoAppId, Integer userId) {
        return mapper.selectCountByQuery(
                QueryWrapper.create().eq(SsoAppAccessPolicy::getSsoAppId, ssoAppId)
                        .eq(SsoAppAccessPolicy::getSubjectType, SsoAppAccessPolicy.SubjectType.USER)
                        .eq(SsoAppAccessPolicy::getSubjectId, userId)
                        .eq(SsoAppAccessPolicy::getEnabled, true)
        ) > 0;
    }

    public boolean checkByUserGroupAccess(Integer ssoAppId, Integer userId) {
        List<SsoAppAccessPolicy> ssoAppAccessPolicies = mapper.selectListByQuery(
                QueryWrapper.create().eq(SsoAppAccessPolicy::getSsoAppId, ssoAppId)
                        .eq(SsoAppAccessPolicy::getSubjectType, SsoAppAccessPolicy.SubjectType.USER_GROUP)
                        .eq(SsoAppAccessPolicy::getEnabled, true)
        );
        List<Integer> groupId = ssoAppAccessPolicies.stream().map(SsoAppAccessPolicy::getSubjectId).toList();
        if (groupId.isEmpty()) {
            return false;
        }
        return ssoUserGroupMappingMapper.selectCountByQuery(
                new QueryWrapper()
                        .in(SsoUserGroupMapping::getSsoUserGroupId, groupId)
                        .eq(SsoUserGroupMapping::getSsoUserId, userId)
        ) > 0;
    }

    public boolean checkByOrganizationAccess(Integer ssoAppId, Integer organizationId) {
        if (organizationId == null) {
            return false;
        }
        List<SsoAppAccessPolicy> ssoAppAccessPolicies = mapper.selectListByQuery(
                QueryWrapper.create().eq(SsoAppAccessPolicy::getSsoAppId, ssoAppId)
                        .eq(SsoAppAccessPolicy::getSubjectType, SsoAppAccessPolicy.SubjectType.ORGANIZATION)
                        .eq(SsoAppAccessPolicy::getEnabled, true)
        );
        List<Integer> organizationIds = ssoAppAccessPolicies.stream().map(SsoAppAccessPolicy::getSubjectId).toList();
        if (organizationIds.isEmpty()) {
            return false;
        }
        //如果有直接返回
        if (organizationIds.contains(organizationId)) {
            return true;
        }
        //检查子节点是否有，有的话也可以
        Set<Integer> organizationIds1 = ssoOrganizationMapper.getOrganizationIds(organizationIds);
        return organizationIds1.contains(organizationId);
    }


    /**
     * 新增单条数据
     *
     * @param entity 实体对象
     */
    public void save(SsoAppAccessPolicy entity) {
        entity.setEnabled(true);
        mapper.insert(entity);
    }

    /**
     * 修改单条数据
     *
     * @param entity 实体对象
     */
    public void update(SsoAppAccessPolicy entity) {
        mapper.update(entity);
    }

    /**
     * 批量删除数据
     *
     * @param ids 主键集合
     */
    public void deleteByIds(List<Integer> ids) {
        mapper.deleteBatchByIds(ids);
    }

    /**
     * 改变状态
     *
     * @param entity
     */
    public void updateEnabled(SsoAppAccessPolicy entity) {
        SsoAppAccessPolicy byId = getById(entity.getSsoAccessPolicyId());
        if (Objects.isNull(byId)) {
            return;
        }
        byId.setEnabled(!byId.getEnabled());
        mapper.update(byId);
    }
}